home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectShow / DMO / DMODemo / dmodemo.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  16.3 KB  |  484 lines

  1. //----------------------------------------------------------------------------
  2. // File: DMODemo.cpp
  3. //
  4. // Desc: The dmodemo sample shows how to stream and playback audio data in a 
  5. //       wave file of reasonable size using DSound Audio Effect DMOs.
  6. //
  7. //       The basic tasks are as follows:
  8. //       1) get the wave file name and DMO name selected by the user
  9. //       2) call CAppStream::Init() to create the Media Object, get
  10. //          interface pointer of IMediaObject and IMediaObjectInPlace,if
  11. //          there is one. Read the wave file into a buffer and read wav format.
  12. //       3) call CAppStream::Stream() to process the data using the Media Object,
  13. //          and retrieve data from the DMO output stream to a buffer in memory.
  14. //       4) create the DSound buffer from the buffer which holds the output data
  15. //          from DMO.
  16. //       5) playback the DSound buffer.
  17. //
  18. // Copyright (c) 1999-2001 Microsoft Corp.  All rights reserved.
  19. //-----------------------------------------------------------------------------
  20. #define STRICT
  21. #include <TCHAR.h>
  22. #include <windows.h>
  23. #include <windowsx.h>
  24. #include <objbase.h>
  25. #include <commdlg.h>
  26. #include <dxerr8.h>
  27. #include <mmsystem.h>
  28. #include <dsound.h>
  29. #include "DSUtil.h"
  30. #include "DXUtil.h"
  31. #include <dmoreg.h>
  32. #include "appstream.h"
  33. #include "wave.h"
  34. #include "resource.h"
  35.  
  36.  
  37. //-----------------------------------------------------------------------------
  38. // Function-prototypes
  39. //-----------------------------------------------------------------------------
  40. INT_PTR CALLBACK MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
  41. HRESULT InitializeAudioEffectDMOList( HWND hDlg, int* iNumDmo );
  42. VOID    OnInitDialog( HWND hDlg );
  43. VOID    OnOpenSoundFile( HWND hDlg );
  44. HRESULT StreamData( HWND hDlg, LPTSTR lpszFileInput, REFCLSID rclsid );
  45. VOID    OnTimer( HWND hDlg );
  46. VOID    EnablePlayUI( HWND hDlg, BOOL bEnable );
  47. VOID    ResetSoundBuffer();
  48. //-----------------------------------------------------------------------------
  49. // Defines, constants, and global variables
  50. //-----------------------------------------------------------------------------
  51. #define MAX_NUM 100
  52. #define APPNAME TEXT("DMO Demo")
  53.  
  54.  
  55. // struct holding DMOs registerd as DMOCATGORY_AUDIO_EFFECT
  56. typedef struct tagDMOINFO {
  57.     TCHAR szName[MAX_NUM];
  58.     CLSID clsidDMO;
  59. } DMOINFO;
  60.  
  61. DMOINFO             g_rgDmoInfo[MAX_PATH];
  62. TCHAR               g_szInputFileName[MAX_PATH];
  63. CSoundManager*      g_pSoundManager = NULL;
  64. CSound*             g_pSound = NULL;
  65.  
  66. //-----------------------------------------------------------------------------
  67. // Name: WinMain()
  68. // Desc: Entry point for the application.  Since we use a simple dialog for 
  69. //       user interaction we don't need to pump messages.
  70. //-----------------------------------------------------------------------------
  71. INT APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, 
  72.                       INT nCmdShow )
  73. {
  74.     // Display the main dialog box.
  75.     DialogBox( hInst, MAKEINTRESOURCE(IDD_MAIN), NULL, MainDlgProc );
  76.  
  77.     return TRUE;
  78. }
  79.  
  80.  
  81. //-----------------------------------------------------------------------------
  82. // Name: MainDlgProc()
  83. // Desc: Handles dialog messages
  84. //-----------------------------------------------------------------------------
  85. INT_PTR CALLBACK MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  86. {
  87.     int iSelectedDMOIndex =0;
  88.     HRESULT hr;
  89.  
  90.     switch( msg ) 
  91.     {
  92.         case WM_INITDIALOG:
  93.             OnInitDialog( hDlg );
  94.             break;
  95.  
  96.         case WM_COMMAND:
  97.             switch( LOWORD(wParam) )
  98.             {
  99.                 case IDC_SOUNDFILE:
  100.                     OnOpenSoundFile( hDlg );
  101.                     break;
  102.  
  103.                 case IDCANCEL:
  104.                     EndDialog( hDlg, IDCANCEL );
  105.  
  106.                     break;
  107.  
  108.                 case IDC_PLAY:
  109.                     iSelectedDMOIndex = ComboBox_GetCurSel( GetDlgItem( hDlg, IDC_DMOCOMBO ) );
  110.                     if( iSelectedDMOIndex < 0 )
  111.                     {
  112.                         MessageBox( hDlg, TEXT("Selecting DMO failed."), TEXT(DEMO_NAME), 
  113.                                     MB_OK | MB_ICONERROR );
  114.                         break;
  115.  
  116.                     }
  117.                     
  118.                     // Very large files may take some time to stream, so update the
  119.                     // window title to indicate progress.
  120.                     SetWindowText( hDlg, TEXT("Reading file...") );
  121.                     hr = StreamData( hDlg, g_szInputFileName, g_rgDmoInfo[iSelectedDMOIndex].clsidDMO );
  122.                     if( FAILED( hr ) )
  123.                     {
  124.                         break;
  125.                     }
  126.  
  127.                       SetWindowText( hDlg, APPNAME );
  128.                     hr = g_pSound->Play( 0,     // lowest priority
  129.                                          0 );   // no flag is set
  130.                     if( FAILED( hr ) )
  131.                     {
  132.                         MessageBox( hDlg, TEXT("Error playing DirectSound buffer.")
  133.                                     , TEXT(DEMO_NAME), 
  134.                                     MB_OK | MB_ICONERROR );
  135.                     }
  136.  
  137.                     EnablePlayUI( hDlg, FALSE );
  138.  
  139.                     break;
  140.  
  141.                 case IDC_STOP:
  142.                     ResetSoundBuffer();                  
  143.                     EnablePlayUI( hDlg, TRUE );
  144.                     break;
  145.  
  146.                 default:
  147.                     return FALSE; // Didn't handle message
  148.             }
  149.             break;
  150.  
  151.         case WM_TIMER:
  152.             OnTimer( hDlg );
  153.             break;
  154.  
  155.         case WM_DESTROY:
  156.             // Cleanup everything
  157.             SAFE_DELETE( g_pSound );
  158.             SAFE_DELETE( g_pSoundManager );
  159.             KillTimer(hDlg, 1);
  160.                 
  161.             break; 
  162.  
  163.         default:
  164.             return FALSE; // Didn't handle message
  165.     }
  166.  
  167.     return TRUE; // Handled message
  168. }
  169.  
  170.  
  171.  
  172.  
  173. //-----------------------------------------------------------------------------
  174. // Name: OnInitDialog()
  175. // Desc: Initializes the dialogs (sets up UI controls, etc.)
  176. //-----------------------------------------------------------------------------
  177. VOID OnInitDialog( HWND hDlg )
  178. {
  179.     int iNumDmo = 0;
  180.     HRESULT hr;
  181.   
  182.     // Load the icon
  183.     HINSTANCE hInst = (HINSTANCE) GetWindowLongPtr( hDlg, GWLP_HINSTANCE );
  184.     HICON hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDR_DEMOICON ) );
  185.  
  186.     // Set the icon for this dialog.
  187.     SendMessage( hDlg, WM_SETICON, ICON_BIG,   (LPARAM) hIcon );  // Set big icon
  188.     SendMessage( hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon );  // Set small icon
  189.  
  190.     // get registered DMOs
  191.     hr = InitializeAudioEffectDMOList( hDlg, &iNumDmo);  
  192.     if( FAILED( hr ) ) {
  193.  
  194.         MessageBox( hDlg, TEXT("Error enumerating DMOs. "), TEXT(DEMO_NAME), 
  195.                                    MB_OK | MB_ICONERROR );
  196.         return;
  197.     }
  198.  
  199.     for(int ii = 0; ii <iNumDmo; ii++){
  200.         ComboBox_AddString(GetDlgItem(hDlg, IDC_DMOCOMBO), g_rgDmoInfo[ii].szName);
  201.     }
  202.     ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_DMOCOMBO), 0);
  203.  
  204.     // CSoundManager creates a CSound buffer.  
  205.     // and sets cooperative level to DSSCL_PRIORITY  (See DirectSound documentation for 
  206.     // more iformation), and set primary buffer format to stereo, 22kHz and 16-bit output.
  207.     g_pSoundManager = new CSoundManager();
  208.     if( g_pSoundManager == NULL )
  209.     {
  210.         MessageBox( hDlg, TEXT("Creating CSoundManager failed."), 
  211.                             TEXT(DEMO_NAME), MB_OK | MB_ICONERROR );
  212.         EndDialog( hDlg, IDCANCEL );
  213.     }
  214.     hr = g_pSoundManager->Initialize( hDlg, DSSCL_PRIORITY, 2, 22050, 16 );
  215.     if( FAILED( hr ) )
  216.     {
  217.         MessageBox( hDlg, TEXT("Error initializing DirectSound."), 
  218.                             TEXT(DEMO_NAME), MB_OK | MB_ICONERROR );
  219.         EndDialog( hDlg, IDCANCEL );
  220.     }
  221.  
  222.    // Set the UI controls
  223.     SetDlgItemText( hDlg, IDC_FILENAME, TEXT("No file loaded.") );
  224.  
  225.     // Create a timer, so we can check for when the soundbuffer is stopped
  226.     SetTimer( hDlg, 0, 250, NULL );    
  227. }
  228.  
  229.  
  230. //-----------------------------------------------------------------------------
  231. // Name: OnOpenSoundFile()
  232. // Desc: Called when the user requests to open a sound file
  233. //-----------------------------------------------------------------------------
  234. VOID OnOpenSoundFile( HWND hDlg ) 
  235. {
  236.     static TCHAR strFileName[MAX_PATH] = TEXT("");
  237.     static TCHAR strPath[MAX_PATH] = TEXT("");
  238.  
  239.     OPENFILENAME ofn;
  240.  
  241.     // Setup the OPENFILENAME structure
  242.     ofn.lStructSize = sizeof(OPENFILENAME);
  243.     ofn.hwndOwner = hDlg;
  244.     ofn.hInstance = NULL;
  245.     ofn.lpstrFilter = TEXT("Wave Files\0*.wav\0All Files\0*.*\0\0");
  246.     ofn.lpstrCustomFilter = NULL;
  247.     ofn.nMaxCustFilter = 0;
  248.     ofn.nFilterIndex= 1;
  249.     ofn.lpstrFile = strFileName;
  250.     ofn.nMaxFile = MAX_PATH;
  251.     ofn.lpstrFileTitle = NULL;
  252.     ofn.nMaxFileTitle = 0;
  253.     ofn.lpstrInitialDir = strPath;
  254.     ofn.lpstrTitle = TEXT("Open Sound File");
  255.     ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
  256.     ofn.nFileOffset = 0;
  257.     ofn.nFileExtension = 0;
  258.     ofn.lpstrDefExt = TEXT(".wav");
  259.     ofn.lCustData = 0;
  260.     ofn.lpfnHook = NULL;
  261.     ofn.lpTemplateName = NULL;
  262.  
  263.     // Get the default media path (something like C:\WINDOWS\MEDIA)
  264.     if( '\0' == strPath[0] )
  265.     {
  266.         UINT uResult = GetWindowsDirectory( strPath, MAX_PATH );
  267.         if( uResult == 0 )
  268.         {
  269.             MessageBox( hDlg, TEXT("GetWindowsDirectory() failed."), 
  270.                             TEXT(DEMO_NAME), MB_OK | MB_ICONERROR );
  271.             return;
  272.         }
  273.         if( lstrcmp( &strPath[lstrlen(strPath)], TEXT("\\") ) )
  274.             lstrcat( strPath, TEXT("\\") );
  275.         lstrcat( strPath, TEXT("MEDIA") );
  276.     }
  277.  
  278.     ResetSoundBuffer();
  279.  
  280.     // Update the UI controls to show the sound as loading a file
  281.     EnableWindow(  GetDlgItem( hDlg, IDC_PLAY ), FALSE);  
  282.     EnableWindow(  GetDlgItem( hDlg, IDC_STOP ), FALSE);    
  283.     SetDlgItemText( hDlg, IDC_FILENAME, TEXT("Loading file...") );
  284.  
  285.     // Display the OpenFileName dialog. Then, try to load the specified file
  286.     if( TRUE != GetOpenFileName( &ofn ) )
  287.     {
  288.         SetDlgItemText( hDlg, IDC_FILENAME, TEXT("Load aborted.") );
  289.         return;
  290.     }
  291.  
  292.     // Update the UI controls to show the sound as the file is loaded
  293.     SetDlgItemText( hDlg, IDC_FILENAME, strFileName );
  294.     EnablePlayUI( hDlg, TRUE );
  295.  
  296.     // Remember the path for next time
  297.     lstrcpy(g_szInputFileName, strFileName);
  298.     lstrcpy( strPath, strFileName );
  299.  
  300.     TCHAR* strLastSlash = _tcsrchr( strPath, '\\' );
  301.     strLastSlash[0] = '\0';
  302. }
  303.  
  304. //-----------------------------------------------------------------------------
  305. // Name: OutputDMOs()
  306. // Desc: Called to fill the combo box
  307. //-----------------------------------------------------------------------------
  308. HRESULT InitializeAudioEffectDMOList( HWND hDlg, int* iNumDmo)
  309. {
  310.  
  311.     IEnumDMO* pEveryRegisterDMOEnum = NULL; 
  312.     HRESULT hrNext;
  313.     DWORD ulNumInfoReturned;
  314.     CLSID clsidCurrentDMO;
  315.     WCHAR* apszDMOName;
  316.  
  317.  
  318.     // Enumerate all the registered DMOs registered as DMOCATEGORY_AUDIO_EFFECT.
  319.     HRESULT hr = DMOEnum( DMOCATEGORY_AUDIO_EFFECT,
  320.                           DMO_ENUMF_INCLUDE_KEYED,
  321.                           0, // Number of input partial media types.
  322.                           NULL,
  323.                           0, // Number of output partial media types.
  324.                           NULL,
  325.                           &pEveryRegisterDMOEnum );
  326.  
  327.     if( FAILED( hr ) ) {
  328.         return hr;
  329.     }
  330.  
  331.     do
  332.     {
  333.         hrNext = pEveryRegisterDMOEnum->Next( 1, &clsidCurrentDMO, &apszDMOName, &ulNumInfoReturned );
  334.         if( FAILED( hrNext ) ) {
  335.             SAFE_RELEASE( pEveryRegisterDMOEnum );
  336.             return hrNext;
  337.         }
  338.     
  339.         if( S_OK == hrNext ) {  
  340. #ifdef _UNICODE
  341.             lstrcpy(g_rgDmoInfo[*iNumDmo].szName,  apszDMOName );
  342. #else
  343.             TCHAR tempStr[MAX_PATH];
  344.             int i = wcstombs(tempStr, apszDMOName, MAX_PATH);
  345.             if( i == -1 )
  346.             {
  347.                 MessageBox( hDlg, TEXT("wcstombs function encountered a wide character that could not be converted to a multibyte character."), 
  348.                             TEXT(DEMO_NAME), MB_OK | MB_ICONERROR );
  349.                 return E_FAIL;
  350.  
  351.             }
  352.  
  353.             lstrcpy(g_rgDmoInfo[*iNumDmo].szName,  tempStr );
  354.  
  355. #endif
  356.             
  357.             CoTaskMemFree( apszDMOName );
  358.  
  359.             g_rgDmoInfo[*iNumDmo].clsidDMO = clsidCurrentDMO;
  360.             
  361.             (*iNumDmo)++;
  362.         }
  363.  
  364.     } while( (S_OK == hrNext) && (*iNumDmo < MAX_NUM) );
  365.  
  366.     SAFE_RELEASE( pEveryRegisterDMOEnum );
  367.     return S_OK;
  368.  
  369. }
  370.  
  371.  
  372. //-----------------------------------------------------------------------------
  373. // Name: StreamData()
  374. // Desc: Called when the user requests to Play
  375. //-----------------------------------------------------------------------------
  376. HRESULT StreamData( HWND hDlg, LPTSTR lpszInputFile, REFGUID rclsid )
  377. {
  378.     HRESULT         hr;
  379.     BYTE            *pbOutData;
  380.     ULONG           uDataSize =0 ;
  381.     LPWAVEFORMATEX  pwfx = NULL;        // pointer to waveformatex structure.
  382.  
  383.     hr = CoInitializeEx( NULL, COINIT_APARTMENTTHREADED );
  384.     if( FAILED ( hr ) ) {
  385.         MessageBox( hDlg, TEXT("Could not initialize COM library."), 
  386.                             TEXT(DEMO_NAME), MB_OK | MB_ICONERROR );
  387.         return hr;
  388.     }
  389.  
  390.     CAppStream*  pStream = new CAppStream();
  391.     if ( !pStream ){
  392.        return E_OUTOFMEMORY;
  393.     }
  394.     hr = pStream->StreamData( lpszInputFile, 
  395.                               rclsid, 
  396.                               hDlg, 
  397.                               &pbOutData, 
  398.                               &uDataSize, 
  399.                               &pwfx );
  400.     if ( FAILED( hr ) ) {
  401.        return hr;
  402.     }
  403.  
  404.     // Free any previous sound, and make a new one
  405.     SAFE_DELETE( g_pSound );
  406.  
  407.     // Load the data from memory into a DirectSound buffer
  408.     hr = g_pSoundManager->CreateFromMemory( &g_pSound, pbOutData,uDataSize, pwfx, DSBCAPS_GLOBALFOCUS, GUID_NULL );
  409.     if( FAILED( hr ) )
  410.     {
  411.         // Not a critical failure, so just update the status
  412.         MessageBox( hDlg, TEXT("Could not create sound buffer."), 
  413.                             TEXT(DEMO_NAME), MB_OK | MB_ICONERROR );
  414.         SetDlgItemText( hDlg, IDC_FILENAME, TEXT("Could not create sound buffer.") );
  415.         return hr; 
  416.     }
  417.  
  418.     SAFE_DELETE_ARRAY( pbOutData );
  419.     SAFE_DELETE ( pStream );
  420.     SafeGlobalFree( pwfx );
  421.  
  422.     CoUninitialize();
  423.     return hr;
  424. }
  425.  
  426.  
  427.  
  428. //-----------------------------------------------------------------------------
  429. // Name: OnTimer()
  430. // Desc: When we think the sound is playing this periodically checks to see if 
  431. //       the sound has stopped.  If it has then updates the dialog.
  432. //-----------------------------------------------------------------------------
  433. VOID OnTimer( HWND hDlg ) 
  434. {
  435.     if( IsWindowEnabled( GetDlgItem( hDlg, IDC_STOP ) ) )
  436.     {
  437.         // We think the sound is playing, so see if it has stopped yet.
  438.         if( !g_pSound->IsSoundPlaying() ) 
  439.         {
  440.             // Update the UI controls to show the sound as stopped
  441.             EnablePlayUI( hDlg, TRUE );
  442.         }
  443.     }
  444. }
  445.  
  446.  
  447.  
  448.  
  449. //-----------------------------------------------------------------------------
  450. // Name: EnablePlayUI( hDlg,)
  451. // Desc: Enables or disables the Play UI controls 
  452. //-----------------------------------------------------------------------------
  453. VOID EnablePlayUI( HWND hDlg, BOOL bEnable )
  454. {
  455.     if( bEnable )
  456.     {      
  457.         EnableWindow(   GetDlgItem( hDlg, IDC_STOP ),       FALSE );
  458.         EnableWindow(   GetDlgItem( hDlg, IDC_PLAY ),       TRUE );
  459.         SetFocus(       GetDlgItem( hDlg, IDC_PLAY ) );
  460.     }
  461.     else
  462.     {        
  463.         EnableWindow(  GetDlgItem( hDlg, IDC_STOP ),       TRUE );
  464.         SetFocus(      GetDlgItem( hDlg, IDC_STOP ) );
  465.         EnableWindow(  GetDlgItem( hDlg, IDC_PLAY ),       FALSE );
  466.     }
  467. }
  468.  
  469. //-----------------------------------------------------------------------------
  470. // Name: ResetSoundBuffer()
  471. // Desc: called when user click stop button or open file button
  472. //-----------------------------------------------------------------------------
  473. VOID ResetSoundBuffer()
  474. {
  475.     if( g_pSound )
  476.     {
  477.         g_pSound->Stop();
  478.         g_pSound->Reset();
  479.     }
  480.  
  481. }
  482.  
  483.  
  484.